﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Research.Kinect.Nui;
using System.Windows;
using System.Windows.Controls;
using System.Runtime.InteropServices;
using System.Windows.Input;
using System.Diagnostics;
using System.Windows.Forms;

namespace Mouse_and_Skyrim_Kinect
{
    public class SkyrimControl
    {
        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        private const int SW_RESTORE = 9;

        private bool startTimer = false;
        private int timer = 0;

        private bool startTimer2 = false;
        private int timer2 = 0;

        private const string processName = "TESV";

        private bool sheathed = true;
        private bool walking = true;

        public void SetProccessWindow()
        {
            Process[] procs = Process.GetProcessesByName(processName);

            if (procs.Count() > 0)
            {
                IntPtr hwnd = procs[0].MainWindowHandle;
                ShowWindowAsync(hwnd, SW_RESTORE);
                SetForegroundWindow(hwnd);
            }
        }

        public void DetermineAction(SkeletonData skeletalData, Canvas canvas, Runtime runtime)
        {
            Joint rightHand = skeletalData.Joints[JointID.HandRight];
            Point rightHandPoint = getDisplayPosition(rightHand, canvas, runtime);

            Joint hipCenter = skeletalData.Joints[JointID.HipCenter];
            Point hipCenterPoint = getDisplayPosition(hipCenter, canvas, runtime);

            Joint shoulderCenter = skeletalData.Joints[JointID.ShoulderCenter];
            Point shoulderCenterPoint = getDisplayPosition(shoulderCenter, canvas, runtime);

            Joint shoulderRight = skeletalData.Joints[JointID.ShoulderRight];
            Point shoulderRightPoint = getDisplayPosition(shoulderRight, canvas, runtime);

            Joint KneeRight = skeletalData.Joints[JointID.KneeRight];
            double kneeRightDepth = getJointDepth(KneeRight, runtime);

            Joint KneeLeft = skeletalData.Joints[JointID.KneeLeft];
            double kneeLeftDepth = getJointDepth(KneeLeft, runtime);


            if (sheathed)
            {
                UnsheathWeapon(rightHandPoint, hipCenterPoint, shoulderCenterPoint);
            }
            else
            {
                LeftWeapon(rightHandPoint, shoulderRightPoint);
            }

            Walk(kneeRightDepth, kneeLeftDepth);
        }

        private void UnsheathWeapon(Point rightHandPoint, Point hipCenterPoint, Point shoulderCenterPoint)
        {
            if (startTimer)
            {
                timer++;
            }

            // Right hand / slide forward
            if (rightHandPoint.Y > hipCenterPoint.Y + 25)
            {
                if (!startTimer)
                {
                    startTimer = true;
                }
            }

            if (rightHandPoint.Y < shoulderCenterPoint.Y && startTimer && timer < 50)
            {
                // Unsheath weapon
                KeyboardControl.SendKey(VirtualKeyCode.VK_R);

                sheathed = false;

                startTimer = false;
                timer = 0;
            }

            if (timer >= 50)
            {
                startTimer = false;
                timer = 0;
            }
        }

        private void LeftWeapon(Point rightHandPoint, Point shoulderRightPoint)
        {
            if (startTimer2)
            {
                timer2++;
            }

            if (rightHandPoint.X > shoulderRightPoint.X + 100)
            {
                if (!startTimer2)
                {
                    startTimer2 = true;
                }
            }

            if (rightHandPoint.X < shoulderRightPoint.X - 50 && startTimer2 && timer2 < 50)
            {
                //MouseControl.SendClick();
                KeyboardControl.MouseLeftClick();

                startTimer2 = false;
                timer2 = 0;
            }

            if (timer2 >= 50)
            {
                startTimer2 = false;
                timer2 = 0;
            }
        }


        private void Walk(double kneeRightDepth, double kneeLeftDepth)
        {
            if (kneeLeftDepth > kneeRightDepth + .5)
            {
                KeyboardControl.KeyDown(VirtualKeyCode.VK_W);
                walking = true;
            }
            else if (walking)
            {
                KeyboardControl.KeyUp(VirtualKeyCode.VK_W);
                walking = false;
            }
        }


        private Point getDisplayPosition(Joint joint, Canvas canvas, Runtime runtime)
        {
            float depthX, depthY;
            runtime.SkeletonEngine.SkeletonToDepthImage(joint.Position, out depthX, out depthY);
            depthX = Math.Max(0, Math.Min(depthX * 320, 320));
            depthY = Math.Max(0, Math.Min(depthY * 240, 240));
            return new Point(depthX, depthY);            
        }

        private double getJointDepth(Joint joint, Runtime runtime)
        {
            short depthValue;
            float depthX, depthY;
            runtime.SkeletonEngine.SkeletonToDepthImage(joint.Position, out depthX, out depthY, out depthValue);

            double depth = depthValue >> 3;
            depth = depth * 0.1 * 0.393700787 / 12;

            return Math.Round(depth, 3);
        }


    }
}
